<template>
  <div class="fm-style">
    <el-container class="fm2-container">
      <el-main class="fm2-main">
        <el-container>
          <!-- 标签 -->
          <el-aside width="250px">
            <filed-bar @addWidget="addWidget" />
          </el-aside>
          <!-- 画板 -->
          <el-container class="center-container" direction="vertical">
            <!-- 画板顶部 -->
            <el-header class="btn-bar" style="height: 45px">
              <slot name="action"> </slot>
              <el-button
                v-if="upload"
                type="text"
                size="medium"
                icon="el-icon-upload2"
                @click="handleUpload"
              >
                {{ $t('fm.actions.import') }}
              </el-button>
              <el-button
                v-if="clearable"
                type="text"
                size="medium"
                icon="el-icon-delete"
                @click="handleClear"
              >
                {{ $t('fm.actions.clear') }}
              </el-button>
              <el-button
                v-if="preview"
                type="text"
                size="medium"
                icon="el-icon-view"
                @click="handlePreview"
              >
                {{ $t('fm.actions.preview') }}
              </el-button>
              <el-button
                v-if="generateJson"
                type="text"
                size="medium"
                icon="el-icon-tickets"
                @click="handleGenerateJson"
              >
                {{ $t('fm.actions.json') }}
              </el-button>
              <el-button
                v-if="generateCode"
                type="text"
                size="medium"
                icon="el-icon-document"
                @click="handleGenerateCode"
              >
                {{ $t('fm.actions.code') }}
              </el-button>
            </el-header>
            <!-- 画板 -->
            <el-main :class="{ 'widget-empty': widgetForm.list.length == 0 }">
              <widget-form
                v-if="!resetJson"
                ref="widgetForm"
                :data="widgetForm"
                :select.sync="widgetFormSelect"
                :remote="remoteFuncs"
              />
            </el-main>
          </el-container>
          <!-- 属性 -->
          <el-aside class="widget-config-container">
            <attribute-bar
              :config="widgetForm"
              :select.sync="widgetFormSelect"
            />
          </el-aside>

          <cus-dialog
            :visible="previewVisible"
            @on-close="previewVisible = false"
            ref="widgetPreview"
            width="1000px"
            form
          >
            <generate-form
              insite="true"
              @on-change="handleDataChange"
              v-if="previewVisible"
              :data="widgetForm"
              :value="widgetModels"
              :remote="remoteFuncs"
              ref="generateForm"
            >
              <template v-slot:blank="scope">
                Width
                <el-input
                  v-model="scope.model.blank.width"
                  style="width: 100px"
                ></el-input>
                Height
                <el-input
                  v-model="scope.model.blank.height"
                  style="width: 100px"
                ></el-input>
              </template>
            </generate-form>

            <template slot="action">
              <el-button type="primary" @click="handleTest">
                {{ $t('fm.actions.getData') }}
              </el-button>
              <el-button @click="handleReset">
                {{ $t('fm.actions.reset') }}
              </el-button>
            </template>
          </cus-dialog>

          <cus-dialog
            :visible="uploadVisible"
            @on-close="uploadVisible = false"
            @on-submit="handleUploadJson"
            ref="uploadJson"
            width="800px"
            form
          >
            <el-alert
              type="info"
              :title="$t('fm.description.uploadJsonInfo')"
            ></el-alert>
            <div id="uploadeditor" style="height: 400px; width: 100%">
              {{ jsonEg }}
            </div>
          </cus-dialog>

          <cus-dialog
            :visible="jsonVisible"
            @on-close="jsonVisible = false"
            ref="jsonPreview"
            width="800px"
            form
          >
            <div id="jsoneditor" style="height: 400px; width: 100%">
              {{ jsonTemplate }}
            </div>

            <template slot="action">
              <el-button
                type="primary"
                class="json-btn"
                :data-clipboard-text="jsonCopyValue"
              >
                {{ $t('fm.actions.copyData') }}
              </el-button>
            </template>
          </cus-dialog>

          <cus-dialog
            :visible="codeVisible"
            @on-close="codeVisible = false"
            ref="codePreview"
            width="800px"
            form
            :action="false"
          >
            <!-- <div id="codeeditor" style="height: 500px; width: 100%;">
              {{htmlTemplate}}
              </div> -->
            <el-tabs
              type="border-card"
              style="box-shadow: none"
              v-model="codeActiveName"
            >
              <el-tab-pane label="Vue Component" name="vue">
                <div id="vuecodeeditor" style="height: 500px; width: 100%">
                  {{ vueTemplate }}
                </div>
              </el-tab-pane>
              <el-tab-pane label="HTML" name="html">
                <div id="codeeditor" style="height: 500px; width: 100%">
                  {{ htmlTemplate }}
                </div>
              </el-tab-pane>
            </el-tabs>
          </cus-dialog>
        </el-container>
      </el-main>
    </el-container>
  </div>
</template>

<script>
import Draggable from 'vuedraggable'
import WidgetConfig from './WidgetConfig'
import FormConfig from './FormConfig'
import WidgetForm from './WidgetForm'
import CusDialog from './CusDialog'
import GenerateForm from './GenerateForm'
import Clipboard from 'clipboard'
import {
  basicComponents,
  layoutComponents,
  advanceComponents,
} from '../configs/componentsConfig.js'
import generateCode from './generateCode.js'
import FiledBar from './fileds/filedBar.vue'
import AttributeBar from './attributes/attributeBar.vue'

export default {
  name: 'fm-making-form',
  components: {
    Draggable,
    WidgetConfig,
    FormConfig,
    WidgetForm,
    CusDialog,
    GenerateForm,
    FiledBar,
    AttributeBar,
  },
  props: {
    preview: {
      type: Boolean,
      default: false,
    },
    generateCode: {
      type: Boolean,
      default: false,
    },
    generateJson: {
      type: Boolean,
      default: false,
    },
    upload: {
      type: Boolean,
      default: false,
    },
    clearable: {
      type: Boolean,
      default: false,
    },
    remoteFuncs: {
      type: Object,
      default: () => ({}),
    },
  },
  data() {
    return {
      basicComponents,
      layoutComponents,
      advanceComponents,
      resetJson: false,
      widgetForm: {
        list: [],
        config: {
          labelWidth: 100,
          labelPosition: 'right',
          size: 'small',
        },
      },
      configTab: 'widget',
      widgetFormSelect: null,
      previewVisible: false,
      jsonVisible: false,
      codeVisible: false,
      uploadVisible: false,
      // remoteFuncs: {
      //   func_test(resolve) {
      //     setTimeout(() => {
      //       const options = [
      //         { id: '1', name: '1111' },
      //         { id: '2', name: '2222' },
      //         { id: '3', name: '3333' },
      //       ]

      //       resolve(options)
      //     }, 2000)
      //   },
      //   funcGetToken(resolve) {
      //     request
      //       .get('http://tools-server.xiaoyaoji.cn/api/uptoken')
      //       .then((res) => {
      //         resolve(res.uptoken)
      //       })
      //   },
      //   upload_callback(response, file, fileList) {
      //     console.log('callback', response, file, fileList)
      //   },
      // },
      widgetModels: {},
      blank: '',
      htmlTemplate: '',
      vueTemplate: '',
      jsonTemplate: '',
      uploadEditor: null,
      jsonCopyValue: '',
      jsonClipboard: null,
      jsonEg: `{
  "list": [],
  "config": {
    "labelWidth": 100,
    "labelPosition": "top",
    "size": "small"
  }
}`,
      codeActiveName: 'vue',
    }
  },
  methods: {
    handleGoGithub() {
      window.location.href = 'https://github.com/GavinZhuLei/vue-form-making'
    },
    handleConfigSelect(value) {
      this.configTab = value
    },
    handleMoveEnd(evt) {
      console.log('end', evt)
    },
    handleMoveStart({ oldIndex }) {
      console.log('start', oldIndex, this.basicComponents)
    },
    handleMove() {
      return true
    },
    handlePreview() {
      this.previewVisible = true
    },
    handleTest() {
      this.$refs.generateForm
        .getData()
        .then((data) => {
          this.$alert(data, '').catch((e) => {})
          this.$refs.widgetPreview.end()
        })
        .catch((e) => {
          this.$refs.widgetPreview.end()
        })
    },
    handleReset() {
      this.$refs.generateForm.reset()
    },
    handleGenerateJson() {
      this.jsonVisible = true
      this.jsonTemplate = this.widgetForm
      console.log(JSON.stringify(this.widgetForm))
      this.$nextTick(() => {
        const editor = ace.edit('jsoneditor')
        editor.session.setMode('ace/mode/json')

        if (!this.jsonClipboard) {
          this.jsonClipboard = new Clipboard('.json-btn')
          this.jsonClipboard.on('success', (e) => {
            this.$message.success(this.$t('fm.message.copySuccess'))
          })
        }
        this.jsonCopyValue = JSON.stringify(this.widgetForm)
      })
    },
    handleGenerateCode() {
      this.codeVisible = true
      this.htmlTemplate = generateCode(JSON.stringify(this.widgetForm), 'html')
      this.vueTemplate = generateCode(JSON.stringify(this.widgetForm), 'vue')
      this.$nextTick(() => {
        const editor = ace.edit('codeeditor')
        editor.session.setMode('ace/mode/html')

        const vueeditor = ace.edit('vuecodeeditor')
        vueeditor.session.setMode('ace/mode/html')
      })
    },
    handleUpload() {
      this.uploadVisible = true
      this.$nextTick(() => {
        this.uploadEditor = ace.edit('uploadeditor')
        this.uploadEditor.session.setMode('ace/mode/json')
      })
    },
    handleUploadJson() {
      try {
        this.setJSON(JSON.parse(this.uploadEditor.getValue()))
        this.uploadVisible = false
      } catch (e) {
        this.$message.error(e.message)
        this.$refs.uploadJson.end()
      }
    },
    handleClear() {
      this.widgetForm = {
        list: [],
        config: {
          labelWidth: 100,
          labelPosition: 'right',
          size: 'small',
          customClass: '',
        },
      }

      this.widgetFormSelect = {}
    },
    clear() {
      this.handleClear()
    },
    getJSON() {
      return this.widgetForm
    },
    getHtml() {
      return generateCode(JSON.stringify(this.widgetForm))
    },
    setJSON(json) {
      this.widgetForm = json
      console.log('SET JSON =============')
      console.log(json)
      if (json.list.length > 0) {
        this.widgetFormSelect = json.list[0]
      }
    },
    handleInput(val) {
      console.log(val)
      this.blank = val
    },
    handleDataChange(field, value, data) {
      console.log(field, value, data)
    },
    addWidget(item) {
      const { list } = this.widgetForm
      const widget = this.addWidgetDefaultAttr(item)
      this.widgetFormSelect = widget
      list.push(widget)
      this.$set(this.widgetForm, 'list', list)
      // this.widgetForm.list.push(item)
    },
    addWidgetDefaultAttr(val) {
      const key =
        Date.parse(new Date().toString()) +
        '_' +
        Math.ceil(Math.random() * 99999)
      let result = {
        ...val,
        key,
        model: val.type + '_' + key,
        rules: [],
      }
      if (['radio', 'checkbox', 'select'].indexOf(val.type) > 0) {
        result = {
          ...result,
          options: {
            ...result.options,
            options: result.options.options.map((item) => ({ ...item })),
          },
        }
      }
      return result
    },
  },
  watch: {
    widgetForm: {
      deep: true,
      handler: function (val) {
        console.log('\n\n------ begin: container widget form change ------')
        console.log(this.$refs.widgetForm)
        console.log('------ end: container widget form change ------\n\n')
      },
    },
  },
}
</script>
